package com.hongyi.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hongyi.common.framework.domain.OperLogEvent;
import com.hongyi.common.framework.utils.DateUtils;
import com.hongyi.common.framework.utils.bean.MapstructUtils;
import com.hongyi.common.framework.utils.common.ArrayUtils;
import com.hongyi.common.framework.utils.ip.AddressUtils;
import com.hongyi.common.framework.utils.string.StringUtils;
import com.hongyi.common.mybatis.page.PageData;
import com.hongyi.common.mybatis.page.PageQuery;
import com.hongyi.system.domain.dto.SysOperLogDto;
import com.hongyi.system.domain.vo.SysOperLogVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import com.hongyi.system.mapper.SysOperLogMapper;
import com.hongyi.system.domain.SysOperLog;
import com.hongyi.system.service.ISysOperLogService;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;

@Service
public class SysOperLogServiceImpl implements ISysOperLogService {

    @Autowired
    private SysOperLogMapper sysOperLogMapper;

    /**
     * 操作日志记录
     *
     * @param operLogEvent 操作日志事件
     */
    @EventListener
    public void recordOper(OperLogEvent operLogEvent) {
        SysOperLogDto operLog = MapstructUtils.convert(operLogEvent, SysOperLogDto.class);
        // 远程查询操作地点
        operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp()));
        insertOperlog(operLog);
    }

    /**
     * 操作日志分页数据
     *
     * @param sysOperLogDto
     * @param pageQuery     分页数据
     * @return 分页数据
     */
    @Override
    public PageData<SysOperLogVo> selectPageOperLogList(SysOperLogDto sysOperLogDto, PageQuery pageQuery) {
        Map<String, Object> params = sysOperLogDto.getParams();
        LambdaQueryWrapper<SysOperLog> lqw = new LambdaQueryWrapper<SysOperLog>()
                .like(StringUtils.isNotBlank(sysOperLogDto.getOperIp()), SysOperLog::getOperIp, sysOperLogDto.getOperIp())
                .like(StringUtils.isNotBlank(sysOperLogDto.getTitle()), SysOperLog::getTitle, sysOperLogDto.getTitle())
                .eq(sysOperLogDto.getBusinessType() != null && sysOperLogDto.getBusinessType() > 0,
                        SysOperLog::getBusinessType, sysOperLogDto.getBusinessType())
                .func(f -> {
                    if (ArrayUtils.isNotEmpty(sysOperLogDto.getBusinessTypes())) {
                        f.in(SysOperLog::getBusinessType, Arrays.asList(sysOperLogDto.getBusinessTypes()));
                    }
                })
                .eq(sysOperLogDto.getStatus() != null,
                        SysOperLog::getStatus, sysOperLogDto.getStatus())
                .like(StringUtils.isNotBlank(sysOperLogDto.getOperName()), SysOperLog::getOperName, sysOperLogDto.getOperName())
                .between(params.get("beginTime") != null && params.get("endTime") != null,
                        SysOperLog::getOperTime, params.get("beginTime"), params.get("endTime"));
        if (StringUtils.isBlank(pageQuery.getOrderByColumn())) {
            pageQuery.setOrderByColumn("oper_id");
            pageQuery.setIsAsc("desc");
        }
        Page<SysOperLogVo> page = sysOperLogMapper.selectVoPage(pageQuery.build(), lqw);
        return PageData.success(page);
    }

    /**
     * 查询系统操作日志集合
     *
     * @param sysOperLogDto
     * @return 操作日志集合
     */
    @Override
    public List<SysOperLogVo> selectOperLogList(SysOperLogDto sysOperLogDto) {
        Map<String, Object> params = sysOperLogDto.getParams();
        return sysOperLogMapper.selectVoList(new LambdaQueryWrapper<SysOperLog>()
                .like(StringUtils.isNotBlank(sysOperLogDto.getOperIp()), SysOperLog::getOperIp, sysOperLogDto.getOperIp())
                .like(StringUtils.isNotBlank(sysOperLogDto.getTitle()), SysOperLog::getTitle, sysOperLogDto.getTitle())
                .eq(sysOperLogDto.getBusinessType() != null && sysOperLogDto.getBusinessType() > 0,
                        SysOperLog::getBusinessType, sysOperLogDto.getBusinessType())
                .func(f -> {
                    if (ArrayUtils.isNotEmpty(sysOperLogDto.getBusinessTypes())) {
                        f.in(SysOperLog::getBusinessType, Arrays.asList(sysOperLogDto.getBusinessTypes()));
                    }
                })
                .eq(sysOperLogDto.getStatus() != null && sysOperLogDto.getStatus() > 0,
                        SysOperLog::getStatus, sysOperLogDto.getStatus())
                .like(StringUtils.isNotBlank(sysOperLogDto.getOperName()), SysOperLog::getOperName, sysOperLogDto.getOperName())
                .between(params.get("beginTime") != null && params.get("endTime") != null,
                        SysOperLog::getOperTime, params.get("beginTime"), params.get("endTime"))
                .orderByDesc(SysOperLog::getOperId));
    }

    /**
     * 新增操作日志
     *
     * @param sysOperLogDto 操作日志对象
     */
    @Override
    public void insertOperlog(SysOperLogDto sysOperLogDto) {
        SysOperLog sysOperLog = MapstructUtils.convert(sysOperLogDto, SysOperLog.class);
        sysOperLog.setOperTime(DateUtils.getNowDate());
        sysOperLogMapper.insert(sysOperLog);

    }

    /**
     * 批量删除系统操作日志
     *
     * @param operIds 需要删除的操作日志ID
     * @return 结果
     */
    @Override
    public int deleteOperLogByIds(Long[] operIds) {
        return sysOperLogMapper.deleteBatchIds(Arrays.asList(operIds));
    }

    /**
     * 清空操作日志
     */
    @Override
    public void cleanOperLog() {
        sysOperLogMapper.delete(new LambdaQueryWrapper<>());
    }
}
